package com.example.sxmall.config;

import com.example.sxmall.auth.Authentication;
import com.example.sxmall.auth.UserInfo;
import com.example.sxmall.auth.UserTestHandler;
import com.example.sxmall.redis.RedisService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.Objects;

/**
 * @author yt
 * @Description: 校验请求token是否有效 拦截器
 */
@Component
@Order(-80)
public class TokenInterceptor implements HandlerInterceptor {

    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private RedisService redisService;

    public static final String TOKEN = "token";

    /**
     * 该方法会在控制器方法前执行，中断后续操作。当其返回值为true时，表示继续向下执行；
     * 当其返回值为false时，会中断后续的所有操作（包括调用下一个拦截器和控制器类中的方法执行等）。
     * HttpServletResponse.SC_UNAUTHORIZED token过期401无权限
     */
    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        Authentication.setUserInfoThreadLocal(null);
        String token = request.getHeader(TOKEN);
        if (StringUtils.isBlank(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        if (StringUtils.equals(UserTestHandler.VISITOR, token)) {
            UserInfo visitor = UserTestHandler.visitor();
            Authentication.setUserInfoThreadLocal(visitor);
            return true;
        }
        //是否为开发环境
        if (StringUtils.equals("dev", active)) {
            if (StringUtils.equals(UserTestHandler.VISITOR, token)) {
                UserInfo visitor = UserTestHandler.visitor();
                Authentication.setUserInfoThreadLocal(visitor);
                return true;
            }
            if (StringUtils.isBlank(token)) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return false;
            }
            UserInfo userInfo = userCenterService.getUserInfoForCache(token);
            Authentication.setUserInfoThreadLocal(userInfo);
            return true;
        }
        UserInfo userInfo = userCenterService.getUserInfoForCache(token);
        if (Objects.isNull(userInfo)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        Authentication.setUserInfoThreadLocal(userInfo);
        return true;
    }

    /**
     * 该方法会在控制器方法调用之后，且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
     */
    @Override
    public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 该方法会在整个请求完成，即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
     */
    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
        Authentication.remove();
    }
}
